package com.gs.netty.client;
import com.gs.netty.support.handler.channel.AbstractChannelDispatchHandler;
import com.gs.netty.support.properties.BaseNettyConfig;

import com.gs.netty.support.codec.RequestResponseAggregator;
import com.gs.netty.websocket.remoting.WebSocketInvocation;
import com.gs.netty.websocket.remoting.req.SocketRequest;
import com.gs.netty.websocket.remoting.req.WebSocketRequest;
import com.gs.netty.websocket.remoting.resp.AppResponse;
import com.gs.netty.websocket.remoting.resp.SocketResponse;
import com.gs.netty.websocket.remoting.resp.WebSocketResponse;
import io.netty.channel.*;
import org.apache.commons.lang3.StringUtils;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;

/**
 * WebSocketNotFountChannelException 请求分发处理器
 */
@ChannelHandler.Sharable
public class WebSocketClientDispatchHandler extends AbstractChannelDispatchHandler<
        AbstractChannelDispatchHandler.WebSocketProcessor> {


    /**
     * 请求响应表
     * key : 请求ID
     * value： 响应参数
     */
    private final ConcurrentHashMap<Integer,ResponseFuture> responseTables = new ConcurrentHashMap<>(256);

    /**
     * 任务对象栈。作用任务对象的频发创建销毁，可以回收利用
     */

    public WebSocketClientDispatchHandler( BaseNettyConfig baseNettyConfig) {
        super(baseNettyConfig);
    }

    public ConcurrentHashMap<Integer, ResponseFuture> getResponseTables() {
        return responseTables;
    }

    @Override
    public void channelRead0(WebSocketInvocation webSocketInvocation,
                             ChannelHandlerContext context) throws Exception {


        Integer requestId = webSocketInvocation.getRequestId();
        ResponseFuture responseFuture = null;
        if (!webSocketInvocation.isRequest()) {

            if ((responseFuture = responseTables.get(requestId)) != null) {
                // 证明该事件是客户端请求响应事件
                responseFuture.setResponseCommand(webSocketInvocation);
                // 移除响应表
                responseTables.remove(requestId);
                // 判断是否存在回调函数
                if (responseFuture.getInvokeCallback() != null) {
                    // 回调
                    executeInvokeCallback(responseFuture);
                } else {
                    // 添加
                    responseFuture.putResponse(webSocketInvocation);
                    // 请求-1
                    responseFuture.release();
                }
            }

        } else  { // 推送
            dispatch(webSocketInvocation,context);
        }
    }


    public void executeInvokeCallback(ResponseFuture responseFuture) {
        boolean runInThisThread = false;
        // 获取线程池
        ExecutorService executor = this.getExecutor();
        // 线程池不为null 就使用线程池来处理
        if (executor != null && !executor.isShutdown()) {
            try {
                executor.submit(() -> {
                    try {
                        // 执行回调
                        responseFuture.executeInvokeCallback();
                    } catch (Throwable e) {
                        log.warn("execute callback in executor exception, and callback throw", e);
                    } finally {
                        responseFuture.release();
                    }
                });
            } catch (Exception e) {
                runInThisThread = true;
                log.warn("execute callback in executor exception, maybe executor busy", e);
            }
        } else {
            runInThisThread = true;
        }
        // 启动当期线程处理
        if (runInThisThread) {
            try {
                // 执行回调
                responseFuture.executeInvokeCallback();
            } catch (Throwable e) {
                log.warn("executeInvokeCallback Exception", e);
            } finally {
                responseFuture.release();
            }
        }
    }
}